unlink Popup menu
動機
特に自動でリンクを貼った場合に使いたい
実装
考察
別の機能と一緒に開発したほうがいいかも
リンクがないときは自動リンクに、リンクを含むときはリンク解除に機能を切り替える
……リンクを追加したい場合にネックになるかな。
リンクを避けて選択しないといけない
別の機能として実装したほうが良さそう?
2023-10-04 07:25:16 TSに移行
リンクを外す処理を変える
hashtagも外すようにした
リンクがあるときだけボタンを表示する
2022-05-24 09:12:44 [(aaa]のように、記号の後にスペースがこないものはリンク扱いする
2022-04-26 10:26:40 数式記法を誤認識していた
2020-09-02 13:46:54 とりあえず作ってみた
code:script.ts
import { Scrapbox } from "../scrapbox-jp%2Ftypes/userscript.ts";
import { getLinks } from "../複数のリンクをまとめて置換するUserScript/mod.ts";
import { convert } from "./mod.ts";
declare const scrapbox: Scrapbox;
scrapbox.PopupMenu.addButton({
title: (text) => getLinks(text).length > 0 ? "\uf127" : "",
onClick: (text) => {
const result = convert(text);
// テロメアが無駄に更新されるのを防ぐ
if(text == result) return;
return result;
}
});
code:mod.ts
import {
CodeBlock,
Line,
Node,
parse,
Table,
} from "../scrapbox-parser/mod.ts";
export const convert = (text: string): string => {
const blocks = parse(text, { hasTitle: false });
return blocks.flatMap((block) => {
switch (block.type) {
case "title":
return [];
case "codeBlock":
return convertCodeBlock(block);
case "table":
return convertTable(block);
case "line":
return convertLine(block);
}
})
.map((line) => line).join("\n");
};
/** コードブロックはそのまま復元する */
const convertCodeBlock = (
{ fileName, content, indent }: CodeBlock,
) => {
const tag = " ".repeat(indent);
return [
${tag}code:${fileName},
...content.split("\n").map((line) => ${tag} ${line}),
];
};
/** テーブル中のリンクを外す */
const convertTable = ({ fileName, cells, indent }: Table) => {
const tag = " ".repeat(indent);
return [
${tag}table:${fileName},
...cells.map((cell) =>
`${tag} ${
cell.map((nodes) => nodes.map((node) => convertNode(node)).join("")).join("\t")
}`
),
];
};
/** 行内リンクを外す */
const convertLine = ({ nodes, indent }: Line) => [
`${" ".repeat(indent)}${
nodes.map((node) => ${convertNode(node)}).join(
"",
)
}`,
];
/** リンクを外したnodeを作る */
const convertNode = (node: Node): string => {
switch (node.type) {
case "quote":
return > ${node.nodes.map((node) => convertNode(node)).join("")};
case "strong":
return [[${node.nodes.map((node) => convertNode(node)).join("")}]];
case "decoration": {
const deco = node.decos.map((deco) => {
const num = parseInt(deco.match(/\*-(\d)/)?.1 ?? "0"); return num > 0 ? "*".repeat(num) : deco;
}).join("");
return [${deco ? ${deco} ` : ""}${
node.nodes.map((node) => convertNode(node)).join("")
}]`;
}
case "hashTag":
return node.href;
// linterのバグで、何故か警告が出る
// deno-lint-ignore no-fallthrough
case "link":
return node.pathType === "absolute" ? node.raw : node.href;
default:
return node.raw;
}
};